#include "rec_read_base.h"
#include "cross_com.h"
#include <chrono>
CRecReadBase::CRecReadBase(int buf_size,int clientID,int channel)
{
	m_curPos     = 0;
//	m_pIdxBuf    = NULL;

//	m_dataOffset = STFS_REC_DATA_OFFSET;
//	m_pIdxBuf    = new STFS_REC_IDX[(STFS_REC_DATA_OFFSET - STFS_REC_IDX_OFFSET)/REC_INDEX_LEN];
//	m_fileStatus = STFS_REC_WRITTING;

	m_playMode   = REPLAY_NORMAL;
    m_pFIFO      = NULL;
	m_speed      = 1;
	m_stepIFrame = 1;
	m_version    = 0;
	m_fileLen    = 0;

	m_channel    = channel;
	m_clientID   = clientID;
	m_startTime	 = 0;
	m_endTime	 = 0;

	m_recOffset	 = 512;
	m_idxOffset  = 0;
	m_fileIdx	 = -1;
	m_nBufSize   = SIZE_4MB;
	m_curTime    = 0;
	m_bDataEnd   = true;
	m_clientID   = 0;
	m_segIdx     = -1;
	m_noReadCount = 0;
	m_bDownload    = false;
	m_fileStartLBA = 0;
	m_bLocalBackup = false;
	m_headOffset  = 0;
	m_headBuf     = new unsigned char[HEAD_BUF_SIZE];
	memset(m_headBuf,0,HEAD_BUF_SIZE);
	m_pFIFO       = new CFrame_sharemem();
	m_lastTime = 0;
	m_lastReadTime = 0;
	m_bComFile = false;

};
CRecReadBase::CRecReadBase()
{

}
CRecReadBase::~CRecReadBase()
{
	if( 0 == m_clientID)
	{
		m_pFIFO = NULL;
	}
	if(NULL != m_headBuf)
	{
		delete [] m_headBuf;
	}
}



void CRecReadBase::StartDataIO()
{
	//加入到读取数据的队列中
	//m_fileStartLBA = GetLoopLBA();
	//TRACE("Dev %s Start Data IO  LBA %lld .\n",m_pFile->get_device_name(),m_fileStartLBA);
	//g_rec_dataIO.AddReaderTask(m_pFile->get_device_name(), m_fileStartLBA,this);

}


int   CRecReadBase::InitFIFOBuf(bool bClearBuf)
{

	int ret = 0;
	if(NULL == m_pFIFO)
	{
		TRACE_ERR("Get Frame FIFO clientID %d bDownload %d .\n",m_clientID, m_bDownload);
		m_pFIFO         = new CFrame_sharemem();
	}
	//if(!m_pFIFO->IsOpen()) //已经打开的情况下不需要再次打开,回放缓存可以调节
	//{
	//	uint32_t bufSz = CStorCacheCfg::getSingleton()->GetReplayBufSz();
	//	ret = m_pFIFO->Open(m_channel,bufSz);
	//}
	//if(bClearBuf)
	//{
	//	m_pFIFO->reset(m_curPos);
	//}

	return ret;
}

void CRecReadBase::Close(bool bImmediate)
{

    TRACE_ERR("ClientID %02d CH%02d \n",m_clientID,m_channel);
//	CCross_LockAuto tempLock(&m_modeLock);

	m_modeLock.lock();
	if(m_bDownload && !bImmediate)
	{
	    TRACE_ERR("ClientID %02d %02d index %d MkEmptyFrame",m_clientID,m_channel,m_fileIdx);
	}
	m_fileLen    = 0;
	m_curIndex   = 0;
	m_bDataEnd   = true;
	//m_startTime	 = 0;
	//m_endTime	 = 0;
	TRACE_ERR("ClientID %02d %02d index %d CRecReadBase::Close \n",m_clientID,m_channel,m_fileIdx);
	m_modeLock.unlock();
}

void CRecReadBase::Clear()
{
	m_fileLen    = 0;
	m_curIndex   = -1;

	m_playMode   = REPLAY_NORMAL;
	m_speed      = 1;
	m_stepIFrame = 1;
	m_bDataEnd   = true;
	if(NULL != m_pFIFO)
	{
		m_pFIFO->reset();
	}
}


//通过数据偏移去定位最近的I帧索引
//
int CRecReadBase::SetPalyMode(int mode,int speed,bool bReSeek)
{
	switch (mode)
	{
	case 	REPLAY_STOP:						//停止
	case	REPLAY_PAUSE:						//暂停
	case	REPLAY_ONEFRAME:					//单帧播放
	case    REPLAY_NORMAL:
	case	REPLAY_SLOW:						//慢进 2, 4, 8, 16, 32
	case	REPLAY_FAST:						//快进 2, 4, 8, 16, 32
	case	REPLAY_REBACK:						//回退 8, 16, 32
		break;
	default:
		TRACE_ERR("Mode is error. speed %d .mode %d \n",m_speed,mode);
		return ERR_PARAM;
	}

	if((mode == m_playMode) && (speed == m_speed))
	{
		//
	//	TRACE_ERR("Mode no changed.\n");
		return 0;
	}

	if(speed >32)
	{
		TRACE_ERR("Speed is error. speed %d .mode %d \n",m_speed,mode);
		return ERR_PARAM;
	}
	m_modeLock.lock();

	if((mode != m_playMode) || (speed != m_speed ))
	{
		//快进， ReadFIFOForward
		//快退,  ReadFIFOReback
		//需要处理进度m_curPos
		if((NULL != m_pFIFO))
		{
			m_curTime = m_lastReadTime;
			TRACE("last time %lld mode %d playmod %d \n",m_curTime,mode,m_playMode);
			PrintTimeMs(m_curTime);
          //  CROSS_ASSERT(m_curTime < STFS_REC_MAX_TIMEMS);
			if(bReSeek)
			{
				SeekToTime(m_curTime,true);
			}
		}

		//Seek(m_curPos);
	}
	m_playMode	= mode;
	m_bDataEnd  = false;

//	m_stepIFrame = speed / STFS_REPLAY_IFRAME_STEP;

	if(m_stepIFrame == 0)
	{
		m_stepIFrame = 1;
	}
	m_speed		= speed;
	m_modeLock.unlock();
    TRACE("Speed %d mode %d step %d\n",m_speed,mode,m_stepIFrame);
	return 0;
}


int CRecReadBase::Read_TO_FIFO(int cache_wather)
{
	int ret = 0;

	ret = m_pFIFO->GetCurWarter();
	if(ret > cache_wather)
	{
	//	if(STFS_READBUF_FULL == ret)
		{
			if(m_noReadCount < 3)
			{
		//		TRACE("clientID%02d CH %02d data is full. m_curIndex %d \n",m_clientID,m_channel,m_curIndex);
		//		PrintTimeMs(m_pFIFO->GetNextFrmTime(),0,"lastFrame Time");
		//		if(m_pIdxBuf[m_curIndex].time != 0)
				{
		//			PrintTimeMs(m_pIdxBuf[m_curIndex].time,0,"Cur Iframe Time");
				}
			}
			m_noReadCount++;
			return 0;
		}
		if(ret > cache_wather + 10)
		{
			m_noReadCount++;
			return 0;
		}
		if(m_noReadCount < 5)
		{
			m_noReadCount++;
			return 0;
		}
	}

	if(m_bDataEnd )
	{
		if(m_bDownload)
        {
            TRACE("CH%02d index%d -%d  Read_TO_FIFO End read file.last offset %d .\n",m_channel,m_fileIdx,m_segIdx,m_curPos);
            return ERR_DATA_AREA;
        }
		return ERR_DATA_AREA;
	}

	m_noReadCount = 0;
//	m_curPos = m_pFile->get_cur_offset();
	if(ret <= 10 || m_bDownload)
	{
//#ifndef _WIN32
//	   TRACE("ClientID %02d CH%02d index %d start read data offset %u mode %d speed %d. step %d water %d \n",
//			m_clientID,m_channel,m_fileIdx,m_pFile->get_cur_offset(),m_playMode,m_speed,m_stepIFrame,ret);
//#endif
	}

//	CCross_LockAuto tempLock(&m_modeLock);
	m_modeLock.lock();
	switch(m_playMode)
	{
	case    REPLAY_NORMAL:
	case	REPLAY_ONEFRAME:					//
	case	REPLAY_SLOW:						//慢放 2, 4, 8, 16, 32
        //if(m_curPos >= STFS_RECORD_SPACE)
        //{
        //    TRACE_ERR("CH%02d index%d  no leaf data curpos%d fileLen %d   End read file.\n",m_channel,m_fileIdx,m_curPos,m_fileLen);
        //    m_bDataEnd = true;
        //    return ERR_DATA_OVER_FILE;
        //}

		ret = ReadFIFONormal();
		break;
	case	REPLAY_FAST:						//快进 2, 4, 8, 16, 32

		if(m_speed <= 1)
		{
			ret = ReadFIFONormal();
		}
		else
		{
			ret = ReadFIFOForward();
		}
		break;
	case	REPLAY_REBACK:						//4 8, 16, 32
		ret = ReadFIFOReback();
		break;
	default:
		ret = ReadFIFONormal();
		break;
	}

	if(ERR_BAD_SECTOR == ret)
	{
		//ret = DealBadSector();
	}
	m_modeLock.unlock();
	return ret;
}


int CRecReadBase::StartRead()
{
	int ret = 0;


	return ret;
}

int CRecReadBase::Read_proc()
{
	int ret = 0;
	int water = 30;

	while (m_bStart)
	{
		Read_TO_FIFO(water);
		this_thread::sleep_for(chrono::milliseconds(3000));
	}

	return ret;
}